#ifndef __FILE_STREAM_H__
#define __FILE_STREAM_H__

#include <cstdint>
#include <cstdio>
#include <cerrno>
#include <cstring>

class FileStream
{
public:
    ~FileStream()
    {
        CloseFile();
    }

    /**
     * @brief 打开文件
     * 
     * @param pcFileName 
     * @param pcModes 
     * @return int32_t 
     */
    int32_t OpenFile(const char* pcFileName, const char* pcModes)
    {
        FILE* pstFile = fopen(pcFileName, pcModes);
        if (pstFile == nullptr)
        {
            return -1;
        }

        m_pstFile = pstFile;

        return 0;
    }

    int32_t Write(const void* pData, size_t ulDataLen)
    {
        if (m_pstFile == nullptr)
        {
            fprintf(stderr, "File had not been opened\n");
            return -1;
        }

        return __Write(pData, ulDataLen);
    }

    int32_t WriteByPos(long lPos, const void* pData, size_t ulDataLen)
    {
        if (m_pstFile == nullptr)
        {
            fprintf(stderr, "File had not been opened\n");
            return -1;
        }

        if (__FSeek(lPos) != 0)
        {
            return 0;
        }

        return __Write(pData, ulDataLen);
    }

    int32_t SetFilePos(long lPos)
    {
        if (m_pstFile == nullptr)
        {
            fprintf(stderr, "File had not been opened\n");
            return -1;
        }

        return __FSeek(lPos);
    }

    long GetFilePos()
    {
        if (m_pstFile == nullptr)
        {
            fprintf(stderr, "File had not been opened\n");
            return -1;
        }

        return ftell(m_pstFile);
    }

    void CloseFile()
    {
        if (m_pstFile != nullptr)
        {
            fclose(m_pstFile);
            m_pstFile = nullptr;
        }
    }
private:
    int32_t __Write(const void* pData, size_t ulDataLen)
    {
        if (fwrite(pData, ulDataLen, 1, m_pstFile) != 1)
        {
            fprintf(stderr, "fwrite error, %s\n", strerror(errno));
            return -1;
        }

        return 0;
    }

    int32_t __FSeek(long lPos)
    {
        if (fseek(m_pstFile, lPos, SEEK_SET) != 0)
        {
            fprintf(stderr, "fseek error, %s\n", strerror(errno));
            return -1;
        }

        return 0;
    }

private:
    FILE* m_pstFile {nullptr};
};

#endif //__FILE_STREAM_H__